/*
 * Copyright (C) Citypassenger Ltd. All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 *
 * You must obey the GNU Affero General Public License in all respects
 * for all of the code used other than OpenSSL.
 */

#include "monit.h"
#include "file_list_loader.h"

#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <unistd.h>
#include <sys/mman.h> //mmap
#include <string.h> //strrchr

int open_file(char* fullname, struct file_list_entry** h) {
        struct stat sb;
        void * addr;
        int fd;
        if (h == NULL)
                return 1;
        fd = open(fullname,  O_RDONLY, 0 );
        if ( fd == 0 )
                return 1;
        if (fstat(fd, &sb) == -1) {
                LogError("%s: cant stat file %s\n", prog, fullname);
                close(fd);
                return 1;
        }
        if (!S_ISREG(sb.st_mode)) {
                LogError("%s: requested file is not regular %s\n", prog, fullname);
                close(fd);
                return 1;
        }
        addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
        if ( addr == 0 ) {
                LogError("%s: cant map file %s\n", prog, fullname);
                close(fd);
                return 1;
        }
        NEW(*h);
        (*h)->fd = fd;
        (*h)->map = addr;
        (*h)->name = fullname;
        (*h)->size = sb.st_size;
        (*h)->type = strrchr(fullname, '.');
        if ( (*h)->type != NULL ) (*h)->type++;
        return 0;
}

int sync_file(char* fullname, struct file_list_entry** h) {
        struct stat sb;
        void * addr;
        int fd;
        if (h == NULL)
                return 1;
        fd = (*h)->fd;
        if ( fd == 0 )
                return 1;
        if (fstat(fd, &sb) == -1) {
                LogError("%s: cant stat file %s\n", prog, fullname);
                close(fd);
                return 1;
        }
        if (!S_ISREG(sb.st_mode)) {
                LogError("%s: requested file is not regular %s\n", prog, fullname);
                close(fd);
                return 1;
        }
        if ((*h)->size == sb.st_size) {
            return 0;
        }
        //not present in openbsd...
        //addr = mremap((*h)->map, (*h)->size, sb.st_size, MREMAP_MAYMOVE);
        munmap((*h)->map, (*h)->size);
        addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
        if ( addr == 0 ) {
                LogError("%s: cant remap file %s\n", prog, fullname);
                close(fd);
                return 1;
        }
        (*h)->map = addr;
        (*h)->size = sb.st_size;
        return 0;
}



